home *** CD-ROM | disk | FTP | other *** search
- // ******************************************************************
- // program written by
- // Paul Baxter
- // MacHack'98
- //
- // ******************************************************************
-
- #include <A4Stuff.h>
- #include <LowMem.h>
- #include "membuddy.h"
-
- #define SYS 0x0500 // sys trap attribute
-
- #define eHandleQueType 'HQ' // que types
- #define ePtrQueType 'PQ'
-
- typedef struct {
- struct QElem *qLink; // next element
- short qType; // always kHandleQueType
- ProcessSerialNumber process;// process number
- Handle theHandle; // Handle
- } HandleQElem;
- typedef HandleQElem* HandleQElemPtr;
-
- typedef struct {
- struct QElem* qLink; // next element
- short qType; // always kHandleQueType
- ProcessSerialNumber process;// process number
- Ptr thePtr; // Pointer
- } PtrQElem;
- typedef PtrQElem* PtrQElemPtr;
-
- asm void MyNewHandle(void); // the patches
- asm void MyNewHandleClear(void);
- asm void MyNewPtr(void);
- asm void MyNewPtrClear(void);
- asm void MyDisposeHandle(void);
- asm void MyDisposePtr(void);
-
- // utility functions
- void AddHandletoQue(Handle theHandle : __A0);
- void RemoveHandleFromQue(Handle theHandle: __A0);
- void AddPtrtoQue(Ptr thePtr : __A0);
- void RemovePointerFromQue(Ptr thePtr: __A0);
- void FreeProcMem(void);
-
- typedef struct { // typedef ques for storing handles and ptrs
- QHdr HandleQue;
- QHdr PointerQue;
- } Ques;
-
-
- Ptr gOldNewHandle = nil; // old and new trap addresses
- Ptr gMyNewHandle = nil;
- Ptr gOldNewHandleClear = nil;
- Ptr gMyNewHandleClear = nil;
- Ptr gOldDisposeHandle = nil;
- Ptr gMyDisposeHandle = nil;
- Ptr gOldDisposePtr = nil;
- Ptr gMyDisposePtr = nil;
- Ptr gOldNewPtr = nil;
- Ptr gMyNewPtr = nil;
- Ptr gOldNewPtrClear = nil;
- Ptr gMyNewPtrClear = nil;
-
- long gNumHandles = 0; // num handles we allocated
- long gNumPtrs = 0; // num pointers we allocated
-
-
- Ques gMyQues; // the que header
- // flag for internal calls
- Boolean gInternalDispose = false;
- // ******************************************************************
- //
- // Main
- // main entry point
- //
- // ******************************************************************
- void main(void)
- {
- Handle myhandle;
-
- EnterCodeResource(); // get globals
-
- // init pointer que
- gMyQues.PointerQue.qFlags = 0;
- gMyQues.PointerQue.qHead = nil;
- gMyQues.PointerQue.qTail = nil;
- // init handle que
- gMyQues.HandleQue.qFlags = 0;
- gMyQues.HandleQue.qHead = nil;
- gMyQues.HandleQue.qTail = nil;
-
- // detach ourselves
- myhandle = Get1Resource('INIT', 0);
- if (myhandle) {
- HLock(myhandle);
- DetachResource(myhandle);
- // install patches
- SetTrap(NewHandle);
- SetTrap(NewHandleClear);
- SetTrap(DisposeHandle);
- SetTrap(NewPtr);
- SetTrap(NewPtrClear);
- SetTrap(DisposePtr);
- }
-
- ExitCodeResource();
- }
-
-
- // ******************************************************************
- //
- // MyNewHandle
- // NewHandle patch
- //
- // ******************************************************************
- asm void MyNewHandle(void)
- {
- Handle newhand; // newly allocated handle
- long size; // allocation size
- long oldA4; // globals ptr
- short trapword; // trap used
-
- fralloc // set stack frame
-
- movem.l D0-D2/A0-A3,-(SP) // save regs
- jsr FreeProcMem
- movem.l (SP)+,D0-D2/A0-A3 // restore regs
-
- movem.l D1/A1-A3,-(SP) // save regs
-
- move.l D0,size // save size
- move.w D1,trapword // save trap word
-
- jsr SetCurrentA4 // set up
- move.l D0, oldA4 // globals
- move.l size, D0 // fix D0 (size)
-
- movea.l gOldNewHandle,A1 // get old trap address
- jsr (A1) // call old routine
- tst.w D0 // check for error
- beq.s @done // noErr just exit
-
- move.w trapword,D1 // get trap word
- cmp.w _NewHandleClear,D1 // _NewHandle = A122
- // _NewHandleClear = A322
- // _NewHandleSys = A522
- // _NewHandleSysClear = A722
- bgt.s @done // if system heap don't try again
-
- move.l size,D0 // restore requested size
- ori.l #SYS,D1 // set system bit
- movea.l gOldNewHandle,A1 // get old trap address
- jsr (A1) // call old routine
-
- tst.w D0 // check result
- bne @done
-
- move.l A0,newhand // save handle
- jsr AddHandletoQue // add it to our que
- move.l newhand,A0 // restore result
- clr.w D0 // we already know there is no error
-
- @done:
- movea.l oldA4,A4 // restore A4
- movem.l (SP)+,D1/A1-A3 // restore regs
- frfree // unlink stack frame
- tst.w D0 // undocumented test for error
-
- rts
- }
-
- // ******************************************************************
- //
- // MyNewHandleClear
- // MyNewHandleClear patch
- //
- // ******************************************************************
- asm void MyNewHandleClear(void)
- {
- Handle newhand; // newly allocated handle
- long size; // allocation size
- long oldA4; // globals ptr
- short trapword; // trap used
-
- fralloc // set stack frame
-
- movem.l D0-D2/A0-A3,-(SP) // save regs
- jsr FreeProcMem
- movem.l (SP)+,D0-D2/A0-A3 // restore regs
-
- movem.l D1/A1-A3,-(SP) // save regs
-
- move.l D0,size // save size
- move.w D1,trapword // save trap word
-
- jsr SetCurrentA4 // set up
- move.l D0, oldA4 // globals
- move.l size, D0 // fix D0 (size)
-
- // get old trap address
- movea.l gOldNewHandleClear,A1
- jsr (A1) // call old routine
- tst.w D0 // check for error
- beq.s @done // noErr just exit
-
- move.w trapword,D1 // get trap word
- cmp.w _NewHandleClear,D1 // _NewHandle = A122
- // _NewHandleClear = A322
- // _NewHandleSys = A522
- // _NewHandleSysClear = A722
- bgt.s @done // if system heap don't try again
-
- move.l size,D0 // restore requested size
- _NewHandleSysClear // try system heap
-
- tst.w D0 // check result
- bne @done
-
- move.l A0,newhand // save handle
- jsr AddHandletoQue // add it to our que
- move.l newhand,A0 // restore result
- clr.w D0 // we already know there is no error
-
- @done:
- movea.l oldA4,A4 // restore A4
- movem.l (SP)+,D1/A1-A3 // restore regs
- frfree // unlink stack frame
- tst.w D0 // undocumented test for error
-
- rts
- }
-
- // ******************************************************************
- //
- // MyNewPtr
- // NewPtr patch
- //
- // ******************************************************************
- asm void MyNewPtr(void)
- {
- long size; // allocation size
- long oldA4; // globals ptr
- short trapword; // trap used
- Ptr thePtr; // pointer allocated
-
- fralloc // set stack frame
-
- movem.l D0-D2/A0-A3,-(SP) // save regs
- jsr FreeProcMem
- movem.l (SP)+,D0-D2/A0-A3 // restore regs
-
- move.l D0,size // save size
- move.w D1,trapword // save trap word
-
- movem.l D1/A1-A3,-(SP) // save regs
-
- jsr SetCurrentA4 // set up
- move.l D0, oldA4 // globals
- move.l size,D0 // fix D0 (size)
-
- movea.l gOldNewPtr,A1 // get old trap address
- jsr (A1) // call old routine
- tst.w D0 // check for error
- beq.s @done // noErr just exit
-
- move.w trapword,D1 // get trap word
- cmp.w #_NewPtrClear,D1 // _NewPtr = A11E
- // _NewPtrClear = A31E
- // _NewPtrSys = A51E
- // _NewPtrSysClear = A71E
-
- bgt.s @done // if system heap don't try again
-
- move.l size,D0 // restore requested size
- ori.l #SYS,D1 // set system bit
- movea.l gOldNewPtr,A1 // get old trap address
- jsr (A1) // call old routine
-
- tst.w D0 // check result
- bne @done
-
- move.l A0,thePtr // save Pointer
- jsr AddPtrtoQue // add it to our que
- move.l thePtr,A0 // restore result
- clr.w D0 // we already know there is no error
-
- @done:
- movea.l oldA4,A4 // restore A4
-
- movem.l (SP)+,D1/A1-A3 // restore regs
-
- frfree // unlink stack frame
- tst.w D0
-
- rts
- }
-
- // ******************************************************************
- //
- // MyNewPtrClear
- // MyNewPtrClear patch
- //
- // ******************************************************************
- asm void MyNewPtrClear(void)
- {
- long size; // allocation size
- long oldA4; // globals ptr
- short trapword; // trap used
- Ptr thePtr; // pointer allocated
-
- fralloc // set stack frame
-
- movem.l D0-D2/A0-A3,-(SP) // save regs
- jsr FreeProcMem
- movem.l (SP)+,D0-D2/A0-A3 // restore regs
-
- move.l D0,size // save size
- move.w D1,trapword // save trap word
-
- movem.l D1/A1-A3,-(SP) // save regs
-
- jsr SetCurrentA4 // set up
- move.l D0, oldA4 // globals
- move.l size,D0 // fix D0 (size)
-
- movea.l gOldNewPtr,A1 // get old trap address
- jsr (A1) // call old routine
- tst.w D0 // check for error
- beq.s @done // noErr just exit
-
- move.w trapword,D1 // get trap word
- cmp.w #_NewPtrClear,D1 // _NewPtr = A11E
- // _NewPtrClear = A31E
- // _NewPtrSys = A51E
- // _NewPtrSysClear = A71E
-
- bgt.s @done // if system heap don't try again
-
- move.l size,D0 // restore requested size
- _NewPtrSysClear // try system heap
-
- tst.w D0 // check result
- bne @done
-
- move.l A0,thePtr // save Pointer
- jsr AddPtrtoQue // add it to our que
- move.l thePtr,A0 // restore result
- clr.w D0 // we already know there is no error
-
- @done:
- movea.l oldA4,A4 // restore A4
-
- movem.l (SP)+,D1/A1-A3 // restore regs
-
- frfree // unlink stack frame
- tst.w D0
-
- rts
- }
-
- // ******************************************************************
- //
- // MyDisposeHandle
- // MyDisposeHandle patch
- //
- // ******************************************************************
- asm void MyDisposeHandle(void)
- {
- long oldA4;
- long theHandle;
- short trapword;
-
- fralloc // set stack frame
-
- move.l A0,theHandle // save handle
- move.w D1,trapword // save trap word
-
- movem.l D0-D2/A0-A3,-(SP) // save regs
- jsr RemoveHandleFromQue
- movem.l (SP)+,D0-D2/A0-A3 // restore regs
-
- movem.l D1/A1,-(SP) // save regs
-
- jsr SetCurrentA4 // set up globals
- move.l D0,oldA4
-
- move.w trapword,D1 // reset trap
- move.l theHandle,A0 // reset handle
- movea.l gOldDisposeHandle,A1// get old trap address
-
- jsr (A1) // call old routine
- movea.l oldA4,A4 // restore A4
-
- movem.l (SP)+,D1/A1 // restore regs
-
- move.l #0,A0
-
- frfree // unlink stack frame
- rts
-
- }
-
- // ******************************************************************
- //
- // MyDisposePtr
- // MyDisposePtr patch
- //
- // ******************************************************************
- asm void MyDisposePtr(void)
- {
- long oldA4;
- long thePtr;
- short trapword;
-
- fralloc // set stack frame
-
- move.l A0,thePtr
- move.w D1,trapword // save trap word
-
-
- movem.l D0-D2/A0-A3,-(SP) // save regs
- jsr RemovePointerFromQue
- movem.l (SP)+,D0-D2/A0-A3 // restore regs
-
- movem.l D1/A1,-(SP) // save regs
-
- jsr SetCurrentA4 // set up globals
- move.l D0,oldA4
- // get old trap address
- move.w trapword,D1
- move.l thePtr,A0
- move.l gOldDisposePtr,A1
-
- jsr (A1) // call old routine
- movea.l oldA4,A4 // restore A4
-
- movem.l (SP)+,D1/A1 // restore regs
-
- frfree // unlink stack frame
- move.l #0,A0
-
- rts
-
- }
-
- // ******************************************************************
- //
- // AddHandletoQue
- // Add a handle to our handle que
- //
- // ******************************************************************
- void AddHandletoQue(Handle theHandle : __A0)
- {
- HandleQElemPtr handleQuePtr;
- ProcessSerialNumber proc;
- OSErr err;
-
- err = GetCurrentProcess(&proc);
- if (!err) {
- handleQuePtr = (HandleQElemPtr)NewPtrSys(sizeof(HandleQElem));
- handleQuePtr->qLink = 0;
- handleQuePtr->qType = eHandleQueType;
-
- handleQuePtr->theHandle = theHandle;
- BlockMoveData(&proc, &handleQuePtr->process, sizeof(ProcessSerialNumber));
- Enqueue((QElem *) handleQuePtr, &gMyQues.HandleQue);
- gNumHandles++;
- }
- }
-
-
- // ******************************************************************
- //
- // AddPtrtoQue
- // Add a pointer to our pointer que
- //
- // ******************************************************************
- void AddPtrtoQue(Ptr thePtr : __A0)
- {
- PtrQElemPtr ptrQuePtr;
- ProcessSerialNumber proc;
- OSErr err;
-
- err = GetCurrentProcess(&proc);
- if (!err) {
- ptrQuePtr = (PtrQElemPtr)NewPtrSys(sizeof(PtrQElem));
- ptrQuePtr->qLink = 0;
- ptrQuePtr->qType = ePtrQueType;
-
- ptrQuePtr->thePtr = thePtr;
- BlockMoveData(&proc, &ptrQuePtr->process, sizeof(ProcessSerialNumber));
- Enqueue((QElem *) ptrQuePtr, &gMyQues.PointerQue);
-
- gNumPtrs++;
- }
- }
-
-
- // ******************************************************************
- //
- // FreeProcMem
- // free memmory if appropriate
- //
- // ******************************************************************
- void FreeProcMem(void)
- {
- ProcessInfoRec procInfo;
- Str255 name;
- FSSpec appSpec;
- HandleQElemPtr handleQuePtr;
- PtrQElemPtr ptrQuePtr;
- unsigned long size;
- OSErr err;
- short resflags;
- Boolean found;
-
- EnterCodeResource();
- gInternalDispose = true;
-
- if ((gNumHandles > 0 || gNumPtrs > 0)) {
-
-
- // kill handles
- do {
- found = true;
- handleQuePtr = (HandleQElemPtr) gMyQues.HandleQue.qHead;
- while (handleQuePtr) {
-
- procInfo.processInfoLength = sizeof(ProcessInfoRec);
- procInfo.processName = name;
- procInfo.processAppSpec = &appSpec;
-
- err = GetProcessInformation(&handleQuePtr->process,&procInfo);
- found = (err == noErr);
- // see if the process is still running
- if (!found) {
- // check resource attribute
- resflags = GetResAttrs(handleQuePtr->theHandle);
- if (ResError()) {
- size = GetHandleSize(handleQuePtr->theHandle);
- if (size) {
- HUnlock(handleQuePtr->theHandle);
- HPurge(handleQuePtr->theHandle);
- DisposeHandle(handleQuePtr->theHandle);
- }
- }
- Dequeue((QElem *)handleQuePtr, &gMyQues.HandleQue);
- gNumHandles--;
- DisposePtr((Ptr)handleQuePtr);
- // DO NOT ZERO OUT handleQuePtr
- break;
- }
- handleQuePtr = (HandleQElemPtr) handleQuePtr->qLink;
- }
- } while (!found);
-
-
- // Kill Pointers
- do {
- found = true;
- ptrQuePtr = (PtrQElemPtr) gMyQues.PointerQue.qHead;
- while (ptrQuePtr) {
-
- procInfo.processInfoLength = sizeof(ProcessInfoRec);
- procInfo.processName = name;
- procInfo.processAppSpec = &appSpec;
-
- err = GetProcessInformation(&ptrQuePtr->process, &procInfo);
- found = (err == noErr);
- // see if the process is still running
- if (!found) {
- size = GetPtrSize(ptrQuePtr->thePtr);
- if (size) {
- DisposePtr(ptrQuePtr->thePtr);
- }
- Dequeue((QElem *)ptrQuePtr, &gMyQues.PointerQue);
- gNumPtrs--;
- DisposePtr((Ptr)ptrQuePtr);
- // DO NOT ZERO OUT ptrQuePtr
- break;
- }
- ptrQuePtr = (PtrQElemPtr) ptrQuePtr->qLink;
- }
- } while (!found);
-
- }
-
- gInternalDispose = false;
-
- ExitCodeResource();
- }
-
- // ******************************************************************
- //
- // RemovePointerFromQue
- // remove a pointer from the pointer que
- //
- // ******************************************************************
- void RemovePointerFromQue(Ptr thePointer: __A0)
- {
- PtrQElemPtr ptrQuePtr;
-
- EnterCodeResource();
-
- if (gInternalDispose) {
- ExitCodeResource();
- return;
- }
-
- ptrQuePtr = (PtrQElemPtr) gMyQues.PointerQue.qHead;
- while (ptrQuePtr) {
- if (ptrQuePtr->thePtr == thePointer) {
- Dequeue((QElem *)ptrQuePtr, &gMyQues.PointerQue);
- gNumPtrs --;
- DisposePtr((Ptr)ptrQuePtr);
- break;
- }
- ptrQuePtr = (PtrQElemPtr) ptrQuePtr->qLink;
- }
-
- ExitCodeResource();
- FreeProcMem();
- }
-
- // ******************************************************************
- //
- // RemoveHandleFromQue
- // remove a handle from the handle que
- //
- // ******************************************************************
- void RemoveHandleFromQue(Handle theHandle: __A0)
- {
- HandleQElemPtr handleQuePtr;
-
- EnterCodeResource();
-
- if (gInternalDispose) {
- ExitCodeResource();
- return;
- }
-
- handleQuePtr = (HandleQElemPtr) gMyQues.HandleQue.qHead;
- while (handleQuePtr) {
- if (handleQuePtr->theHandle == theHandle) {
- Dequeue((QElem *)handleQuePtr, &gMyQues.HandleQue);
- gNumHandles--;
- DisposePtr((Ptr)handleQuePtr);
- break;
- }
- handleQuePtr = (HandleQElemPtr) handleQuePtr->qLink;
- }
- ExitCodeResource();
-
- FreeProcMem();
-
- }